Masthead

Painting in Qt

The sample below shows a simple example of painting in a window with the Qt library.

############################################################################
# Projection Explorer for Python
# This version is specifically for developing the code that provides
# Projection grids for websites
#
# http://zetcode.com/gui/pyqt5/painting/
# https://doc.qt.io/qt-5/qpen.html
############################################################################
import sys
import os
from PyQt5.QtWidgets import *
from PyQt5 import *
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QColor, QFont,QPen
from PyQt5.QtCore import QTimer

#################################################################
# Definitions
#################################################################
WINDOW_WIDTH=600
WINDOW_HEIGHT=600

#################################################################
# Agent class.  This class creates objects for each agent.
# Each agent as a coordinate for their position, a color,
# and a movement amount.  The agents could be expanded to include
# life stages, age, hunger, reproduction, and feeding.
#################################################################

class AgentClass:
	""" Initialize the new object
	 Inputs:
	  canvas - the canvas widget that the agent will appear in
	  Position - a list of the x and y pixel coordinate for the starting location of the agent
	  FillColor - the color of the Agent
	  MovementAmount - The Amount to move the Agent for each time Move() is called
	"""
	def __init__(self, TheCanvas, Coordinate, Red,Green,Blue, MovementAmount):

		self.TheCanvas = TheCanvas # save the canvas the Agent is in

		# save the amount to move for later
		self.MovementAmount = MovementAmount

		self.Coordinate=Coordinate
		
		self.TheCanvas=TheCanvas
		
		self.Color=QColor(Red,Green,Blue)

	def Paint(self,ThePainter):
		""" paint the agent's symbol """
		ThePainter.setBrush(self.Color) # set a different color
		
		Coordinate=self.Coordinate
		ThePainter.drawEllipse(Coordinate[0], Coordinate[1],20,20) # draw an ellipse
		
	def move(self):
		""" Move the Agent object """
		# get the existing coordinate of the agent
		Coordinate = self.Coordinate

		Coordinate[0]=Coordinate[0]+self.MovementAmount
		
		# if the Agent has moved off the frame, reverse the direction of movement
		if Coordinate[0] >= WINDOW_WIDTH:
			self.MovementAmount = -self.MovementAmount
		if Coordinate[0] < 0:
			self.MovementAmount = -self.MovementAmount

		# update the Agent in the canvas
		#self.TheCanvas.move(self.id, self.MovementAmount, 0)
		
######################################################################################################
# Main Window
######################################################################################################
class CanvasWidget(QLabel):
	########################################################################################################
	# Construction Function
	########################################################################################################
	def __init__(self):
		super().__init__()

		#########################################################
		# Setup the agents (Agent)
	
		#Create four Agent objects
		self.TheItems = [
			AgentClass(self, [100, 50], 200, 0, 0, 2),
			AgentClass(self,[100, 80], 0, 200, 0, -1),
			AgentClass(self, [100, 120], 120,120,120, 1),
			AgentClass(self, [100, 150], 0,0,200, -2)
		]
	########################################################################################################
	def paintEvent(self, event):
		""" Override the widgets paint event function to do our own painting """
		# Create a painting object
		ThePainter = QPainter()

		# Start the painting
		ThePainter.begin(self) # everything between here and the end() call will be drawn into the Widget

		# Paint all of the agents
		Index=0
		while Index<len(self.TheItems):
			self.TheItems[Index].Paint(ThePainter)
			Index+=1
			
		ThePainter.end() # finishing drawing

	########################################################################################################
	def Update(self):
		""" Update all of the agents.  Currently this consists of just moving them but this  loop
		could have them move, feed, give birth, die, etc. """
		Index=0
		while Index<len(self.TheItems):
			TheItem=self.TheItems[Index]
			TheItem.move()
			Index+=1
		
		self.update()
######################################################################################################
# Function called by the timer
######################################################################################################
def UpdateWindow():
	""" We need to have a function that the timer can call.  This function just calls the main window
	to have it update the agents on each timer interval """
	TheWindow.Update()

######################################################################################################
# Main Window
######################################################################################################
class WindowClass(QWidget):
	"""
	A window class that includes a widget that contains agents that move
	"""
	##################################################################################################
	## Initialization
	def __init__(self):
		super().__init__()
		#########################################################
		# Create a vertical layout box for the entire window
		MainLayout = QVBoxLayout()
	
		# Add a frame to the main window's layout
		TheFrame = QFrame(self)
		TheFrame.setFrameShape(QFrame.StyledPanel)
		MainLayout.addWidget(TheFrame)
	
		# Add a box layout into the frame
		SettingsLayout = QVBoxLayout()
		TheFrame.setLayout(SettingsLayout)
	
		#########################################################
		# Create a canvas to draw into
	
		self.TheCanvas = CanvasWidget() # create the canvas widget that will do the painting
		SettingsLayout.addWidget(self.TheCanvas)  # add the canvas to the layout within the frame
	
		#########################################################
		# Setup the overall window
	
		# Set the vertical layout as the main layout for the window
		self.setLayout(MainLayout) 
		# set the initial size of the window
		self.setGeometry(100, 100, WINDOW_WIDTH, WINDOW_HEIGHT)
	
		# Set the title of the window and call show() to make the window appear
		self.setWindowTitle('Painting')
		
		#########################################################
		# Show the window to the user
		self.show()

	##################################################################################################
	## Periodic updates
	def Update(self):
		""" Updates the agents within the canvas widget """
		self.TheCanvas.Update()
		
	
#########################################################
# Create the application and the main window.
#########################################################
	
TheApplication = QApplication(sys.argv) # create a PyQt application
TheWindow = WindowClass() # Create our window object and the agents inside of it

#########################################################
# Setup a timer 
#########################################################
timer = QTimer()
timer.timeout.connect(UpdateWindow)
timer.start(10)

#########################################################
# Run the program until the user closes it
#########################################################
sys.exit(TheApplication.exec_()) # Start the application

 

© Copyright 2018 HSU - All rights reserved.